
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="zh_Hans">
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>全文搜索 &#8212; Django 3.2.6.dev 文档</title>
    <link rel="stylesheet" href="../../../_static/default.css" type="text/css" />
    <link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" />
    <script type="text/javascript" id="documentation_options" data-url_root="../../../" src="../../../_static/documentation_options.js"></script>
    <script type="text/javascript" src="../../../_static/jquery.js"></script>
    <script type="text/javascript" src="../../../_static/underscore.js"></script>
    <script type="text/javascript" src="../../../_static/doctools.js"></script>
    <script type="text/javascript" src="../../../_static/language_data.js"></script>
    <link rel="index" title="索引" href="../../../genindex.html" />
    <link rel="search" title="搜索" href="../../../search.html" />
    <link rel="next" title="验证器" href="validators.html" />
    <link rel="prev" title="数据库迁移操作" href="operations.html" />



 
<script src="../../../templatebuiltins.js"></script>
<script>
(function($) {
    if (!django_template_builtins) {
       // templatebuiltins.js missing, do nothing.
       return;
    }
    $(document).ready(function() {
        // Hyperlink Django template tags and filters
        var base = "../../templates/builtins.html";
        if (base == "#") {
            // Special case for builtins.html itself
            base = "";
        }
        // Tags are keywords, class '.k'
        $("div.highlight\\-html\\+django span.k").each(function(i, elem) {
             var tagname = $(elem).text();
             if ($.inArray(tagname, django_template_builtins.ttags) != -1) {
                 var fragment = tagname.replace(/_/, '-');
                 $(elem).html("<a href='" + base + "#" + fragment + "'>" + tagname + "</a>");
             }
        });
        // Filters are functions, class '.nf'
        $("div.highlight\\-html\\+django span.nf").each(function(i, elem) {
             var filtername = $(elem).text();
             if ($.inArray(filtername, django_template_builtins.tfilters) != -1) {
                 var fragment = filtername.replace(/_/, '-');
                 $(elem).html("<a href='" + base + "#" + fragment + "'>" + filtername + "</a>");
             }
        });
    });
})(jQuery);</script>

  </head><body>

    <div class="document">
  <div id="custom-doc" class="yui-t6">
    <div id="hd">
      <h1><a href="../../../index.html">Django 3.2.6.dev 文档</a></h1>
      <div id="global-nav">
        <a title="Home page" href="../../../index.html">Home</a>  |
        <a title="Table of contents" href="../../../contents.html">Table of contents</a>  |
        <a title="Global index" href="../../../genindex.html">Index</a>  |
        <a title="Module index" href="../../../py-modindex.html">Modules</a>
      </div>
      <div class="nav">
    &laquo; <a href="operations.html" title="数据库迁移操作">previous</a>
     |
    <a href="../../index.html" title="API 参考" accesskey="U">up</a>
   |
    <a href="validators.html" title="验证器">next</a> &raquo;</div>
    </div>

    <div id="bd">
      <div id="yui-main">
        <div class="yui-b">
          <div class="yui-g" id="ref-contrib-postgres-search">
            
  <div class="section" id="s-full-text-search">
<span id="full-text-search"></span><h1>全文搜索<a class="headerlink" href="#full-text-search" title="永久链接至标题">¶</a></h1>
<p><code class="docutils literal notranslate"><span class="pre">django.contrib.postgres.search</span></code> 模块中的数据库函数方便了 PostgreSQL 的 <a class="reference external" href="https://www.postgresql.org/docs/current/textsearch.html">全文搜索引擎</a> 的使用。</p>
<p>在本文档的例子中，我们将使用 <a class="reference internal" href="../../../topics/db/queries.html"><span class="doc">Making queries</span></a> 中定义的模型。</p>
<div class="admonition seealso">
<p class="first admonition-title">参见</p>
<p class="last">有关搜索的高级概述，请参见 <a class="reference internal" href="../../../topics/db/search.html"><span class="doc">主题文档</span></a>。</p>
</div>
<div class="section" id="s-the-search-lookup">
<span id="the-search-lookup"></span><h2><code class="docutils literal notranslate"><span class="pre">search</span></code> 查找<a class="headerlink" href="#the-search-lookup" title="永久链接至标题">¶</a></h2>
<p id="std:fieldlookup-search">使用全文检索的常见方法是针对数据库中的单一列进行单项检索。例如：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">Entry</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">body_text__search</span><span class="o">=</span><span class="s1">&#39;Cheese&#39;</span><span class="p">)</span>
<span class="go">[&lt;Entry: Cheese on Toast recipes&gt;, &lt;Entry: Pizza Recipes&gt;]</span>
</pre></div>
</div>
<p>这将使用默认的数据库搜索配置，从 <code class="docutils literal notranslate"><span class="pre">body_text</span></code> 字段在数据库中创建一个 <code class="docutils literal notranslate"><span class="pre">to_tsvector</span></code>，从搜索词 <code class="docutils literal notranslate"><span class="pre">'Cheese'</span></code> 中创建一个 <code class="docutils literal notranslate"><span class="pre">plainto_tsquery</span></code>。通过匹配查询和向量得到结果。</p>
<p>要使用 <code class="docutils literal notranslate"><span class="pre">search</span></code> 查找，<code class="docutils literal notranslate"><span class="pre">'django.contrib.postgres'</span></code> 必须在你的 <a class="reference internal" href="../../settings.html#std:setting-INSTALLED_APPS"><code class="xref std std-setting docutils literal notranslate"><span class="pre">INSTALLED_APPS</span></code></a>。</p>
<div class="versionchanged">
<span class="title">Changed in Django 3.1:</span> <p>增加了对查询表达式的支持。</p>
</div>
</div>
<div class="section" id="s-searchvector">
<span id="searchvector"></span><h2><code class="docutils literal notranslate"><span class="pre">SearchVector</span></code><a class="headerlink" href="#searchvector" title="永久链接至标题">¶</a></h2>
<dl class="class">
<dt id="django.contrib.postgres.search.SearchVector">
<em class="property">class </em><code class="descname">SearchVector</code>(<em>*expressions</em>, <em>config=None</em>, <em>weight=None</em>)<a class="headerlink" href="#django.contrib.postgres.search.SearchVector" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>对单个字段进行搜索是很好的，但有很大的局限性。我们要搜索的 <code class="docutils literal notranslate"><span class="pre">Entry</span></code> 实例属于 <code class="docutils literal notranslate"><span class="pre">Blog</span></code>，它有一个 <code class="docutils literal notranslate"><span class="pre">tagline</span></code> 字段。要对这两个字段进行查询，使用 <code class="docutils literal notranslate"><span class="pre">SearchVector</span></code>：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.contrib.postgres.search</span> <span class="kn">import</span> <span class="n">SearchVector</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Entry</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">annotate</span><span class="p">(</span>
<span class="gp">... </span>    <span class="n">search</span><span class="o">=</span><span class="n">SearchVector</span><span class="p">(</span><span class="s1">&#39;body_text&#39;</span><span class="p">,</span> <span class="s1">&#39;blog__tagline&#39;</span><span class="p">),</span>
<span class="gp">... </span><span class="p">)</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">search</span><span class="o">=</span><span class="s1">&#39;Cheese&#39;</span><span class="p">)</span>
<span class="go">[&lt;Entry: Cheese on Toast recipes&gt;, &lt;Entry: Pizza Recipes&gt;]</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">SearchVector</span></code> 的参数可以是任何 <a class="reference internal" href="../../models/expressions.html#django.db.models.Expression" title="django.db.models.Expression"><code class="xref py py-class docutils literal notranslate"><span class="pre">Expression</span></code></a> 或字段名。多个参数将使用空格连接在一起，这样搜索文档就会包含所有参数。</p>
<p><code class="docutils literal notranslate"><span class="pre">SearchVector</span></code> 对象可以组合在一起，允许你重复使用它们。例如：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">Entry</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">annotate</span><span class="p">(</span>
<span class="gp">... </span>    <span class="n">search</span><span class="o">=</span><span class="n">SearchVector</span><span class="p">(</span><span class="s1">&#39;body_text&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="n">SearchVector</span><span class="p">(</span><span class="s1">&#39;blog__tagline&#39;</span><span class="p">),</span>
<span class="gp">... </span><span class="p">)</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">search</span><span class="o">=</span><span class="s1">&#39;Cheese&#39;</span><span class="p">)</span>
<span class="go">[&lt;Entry: Cheese on Toast recipes&gt;, &lt;Entry: Pizza Recipes&gt;]</span>
</pre></div>
</div>
<p>关于 <code class="docutils literal notranslate"><span class="pre">config</span></code> 和 <code class="docutils literal notranslate"><span class="pre">weight</span></code> 参数的解释，请参见 <a class="reference internal" href="#postgresql-fts-search-configuration"><span class="std std-ref">更改搜索配置</span></a> 和 <a class="reference internal" href="#postgresql-fts-weighting-queries"><span class="std std-ref">加权查询</span></a>。</p>
</div>
<div class="section" id="s-searchquery">
<span id="searchquery"></span><h2><code class="docutils literal notranslate"><span class="pre">SearchQuery</span></code><a class="headerlink" href="#searchquery" title="永久链接至标题">¶</a></h2>
<dl class="class">
<dt id="django.contrib.postgres.search.SearchQuery">
<em class="property">class </em><code class="descname">SearchQuery</code>(<em>value</em>, <em>config=None</em>, <em>search_type='plain'</em>)<a class="headerlink" href="#django.contrib.postgres.search.SearchQuery" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p><code class="docutils literal notranslate"><span class="pre">SearchQuery</span></code> 将用户提供的术语转化为搜索查询对象，数据库将其与搜索向量进行比较。默认情况下，用户提供的所有词语都会通过词干算法，然后寻找所有结果词语的匹配。</p>
<p>如果 <code class="docutils literal notranslate"><span class="pre">search_type</span></code> 是 <code class="docutils literal notranslate"><span class="pre">'plain'</span></code>，即默认值，则将术语作为单独的关键字处理。如果 <code class="docutils literal notranslate"><span class="pre">search_type</span></code> 是 <code class="docutils literal notranslate"><span class="pre">'phrase'</span></code>，则将术语作为一个单一的短语处理。如果 <code class="docutils literal notranslate"><span class="pre">search_type</span></code> 是 <code class="docutils literal notranslate"><span class="pre">'raw'</span></code>，那么你可以提供一个带有术语和运算符的格式化搜索查询。如果 <code class="docutils literal notranslate"><span class="pre">search_type</span></code> 是 <code class="docutils literal notranslate"><span class="pre">'websearch'</span></code>，那么你可以提供一个格式化的搜索查询，类似于网络搜索引擎使用的格式。<code class="docutils literal notranslate"><span class="pre">'websearch'</span></code> 需要 PostgreSQL ≥ 11。请阅读 PostgreSQL 的 <a class="reference external" href="https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES">全文搜索文档</a> 来了解两者的区别和语法。举例说明。</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.contrib.postgres.search</span> <span class="kn">import</span> <span class="n">SearchQuery</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">SearchQuery</span><span class="p">(</span><span class="s1">&#39;red tomato&#39;</span><span class="p">)</span>  <span class="c1"># two keywords</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">SearchQuery</span><span class="p">(</span><span class="s1">&#39;tomato red&#39;</span><span class="p">)</span>  <span class="c1"># same results as above</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">SearchQuery</span><span class="p">(</span><span class="s1">&#39;red tomato&#39;</span><span class="p">,</span> <span class="n">search_type</span><span class="o">=</span><span class="s1">&#39;phrase&#39;</span><span class="p">)</span>  <span class="c1"># a phrase</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">SearchQuery</span><span class="p">(</span><span class="s1">&#39;tomato red&#39;</span><span class="p">,</span> <span class="n">search_type</span><span class="o">=</span><span class="s1">&#39;phrase&#39;</span><span class="p">)</span>  <span class="c1"># a different phrase</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">SearchQuery</span><span class="p">(</span><span class="s2">&quot;&#39;tomato&#39; &amp; (&#39;red&#39; | &#39;green&#39;)&quot;</span><span class="p">,</span> <span class="n">search_type</span><span class="o">=</span><span class="s1">&#39;raw&#39;</span><span class="p">)</span>  <span class="c1"># boolean operators</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">SearchQuery</span><span class="p">(</span><span class="s2">&quot;&#39;tomato&#39; (&#39;red&#39; OR &#39;green&#39;)&quot;</span><span class="p">,</span> <span class="n">search_type</span><span class="o">=</span><span class="s1">&#39;websearch&#39;</span><span class="p">)</span>  <span class="c1"># websearch operators</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">SearchQuery</span></code> 术语可以按逻辑组合，以提供更大的灵活性：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.contrib.postgres.search</span> <span class="kn">import</span> <span class="n">SearchQuery</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">SearchQuery</span><span class="p">(</span><span class="s1">&#39;meat&#39;</span><span class="p">)</span> <span class="o">&amp;</span> <span class="n">SearchQuery</span><span class="p">(</span><span class="s1">&#39;cheese&#39;</span><span class="p">)</span>  <span class="c1"># AND</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">SearchQuery</span><span class="p">(</span><span class="s1">&#39;meat&#39;</span><span class="p">)</span> <span class="o">|</span> <span class="n">SearchQuery</span><span class="p">(</span><span class="s1">&#39;cheese&#39;</span><span class="p">)</span>  <span class="c1"># OR</span>
<span class="gp">&gt;&gt;&gt; </span><span class="o">~</span><span class="n">SearchQuery</span><span class="p">(</span><span class="s1">&#39;meat&#39;</span><span class="p">)</span>  <span class="c1"># NOT</span>
</pre></div>
</div>
<p>参见 <a class="reference internal" href="#postgresql-fts-search-configuration"><span class="std std-ref">更改搜索配置</span></a> 对 <code class="docutils literal notranslate"><span class="pre">config</span></code> 参数的解释。</p>
<div class="versionchanged">
<span class="title">Changed in Django 3.1:</span> <p>在 <code class="docutils literal notranslate"><span class="pre">SearchQuery.value</span></code> 中增加了对 <code class="docutils literal notranslate"><span class="pre">'websearch'</span></code> 搜索类型和查询表达式的支持。</p>
</div>
</div>
<div class="section" id="s-searchrank">
<span id="searchrank"></span><h2><code class="docutils literal notranslate"><span class="pre">SearchRank</span></code><a class="headerlink" href="#searchrank" title="永久链接至标题">¶</a></h2>
<dl class="class">
<dt id="django.contrib.postgres.search.SearchRank">
<em class="property">class </em><code class="descname">SearchRank</code>(<em>vector</em>, <em>query</em>, <em>weights=None</em>, <em>normalization=None</em>, <em>cover_density=False</em>)<a class="headerlink" href="#django.contrib.postgres.search.SearchRank" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>到目前为止，我们已经返回了向量和查询之间可能匹配的结果。很可能你会希望按照某种相关性对结果进行排序。PostgreSQL 提供了一个排序函数，它考虑了查询术语在文档中出现的频率，术语在文档中的相近程度，以及它们出现的部分在文档中的重要性。匹配度越高，排名值越高。要按相关性排序：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.contrib.postgres.search</span> <span class="kn">import</span> <span class="n">SearchQuery</span><span class="p">,</span> <span class="n">SearchRank</span><span class="p">,</span> <span class="n">SearchVector</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">vector</span> <span class="o">=</span> <span class="n">SearchVector</span><span class="p">(</span><span class="s1">&#39;body_text&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">query</span> <span class="o">=</span> <span class="n">SearchQuery</span><span class="p">(</span><span class="s1">&#39;cheese&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Entry</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">annotate</span><span class="p">(</span><span class="n">rank</span><span class="o">=</span><span class="n">SearchRank</span><span class="p">(</span><span class="n">vector</span><span class="p">,</span> <span class="n">query</span><span class="p">))</span><span class="o">.</span><span class="n">order_by</span><span class="p">(</span><span class="s1">&#39;-rank&#39;</span><span class="p">)</span>
<span class="go">[&lt;Entry: Cheese on Toast recipes&gt;, &lt;Entry: Pizza recipes&gt;]</span>
</pre></div>
</div>
<p>参见 <a class="reference internal" href="#postgresql-fts-weighting-queries"><span class="std std-ref">加权查询</span></a> 关于 <code class="docutils literal notranslate"><span class="pre">weights</span></code> 参数的解释。</p>
<p>将 <code class="docutils literal notranslate"><span class="pre">cover_density</span></code> 参数设置为 <code class="docutils literal notranslate"><span class="pre">True</span></code>，启用覆盖密度排序，即考虑匹配的查询词的接近程度。</p>
<p>为 <code class="docutils literal notranslate"><span class="pre">normalization</span></code> 参数提供一个整数，以控制等级标准化。这个整数是一个位掩码，所以你可以结合多种行为：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.db.models</span> <span class="kn">import</span> <span class="n">Value</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Entry</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">annotate</span><span class="p">(</span>
<span class="gp">... </span>    <span class="n">rank</span><span class="o">=</span><span class="n">SearchRank</span><span class="p">(</span>
<span class="gp">... </span>        <span class="n">vector</span><span class="p">,</span>
<span class="gp">... </span>        <span class="n">query</span><span class="p">,</span>
<span class="gp">... </span>        <span class="n">normalization</span><span class="o">=</span><span class="n">Value</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">bitor</span><span class="p">(</span><span class="n">Value</span><span class="p">(</span><span class="mi">4</span><span class="p">)),</span>
<span class="gp">... </span>    <span class="p">)</span>
<span class="gp">... </span><span class="p">)</span>
</pre></div>
</div>
<p>PostgreSQL 文档中有更多关于 <a class="reference external" href="https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-RANKING">不同排序归一化选项</a> 的细节。</p>
<div class="versionadded">
<span class="title">New in Django 3.1:</span> <p>增加了 <code class="docutils literal notranslate"><span class="pre">normalization</span></code> 和 <code class="docutils literal notranslate"><span class="pre">cover_density</span></code> 参数。</p>
</div>
</div>
<div class="section" id="s-searchheadline">
<span id="searchheadline"></span><h2><code class="docutils literal notranslate"><span class="pre">SearchHeadline</span></code><a class="headerlink" href="#searchheadline" title="永久链接至标题">¶</a></h2>
<div class="versionadded">
<span class="title">New in Django 3.1.</span> </div>
<dl class="class">
<dt id="django.contrib.postgres.search.SearchHeadline">
<em class="property">class </em><code class="descname">SearchHeadline</code>(<em>expression</em>, <em>query</em>, <em>config=None</em>, <em>start_sel=None</em>, <em>stop_sel=None</em>, <em>max_words=None</em>, <em>min_words=None</em>, <em>short_word=None</em>, <em>highlight_all=None</em>, <em>max_fragments=None</em>, <em>fragment_delimiter=None</em>)<a class="headerlink" href="#django.contrib.postgres.search.SearchHeadline" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>接受一个文本字段或一个表达式、一个查询、一个配置和一组选项。返回高亮显示的搜索结果。</p>
<p>将 <code class="docutils literal notranslate"><span class="pre">start_sel</span></code> 和 <code class="docutils literal notranslate"><span class="pre">stop_sel</span></code> 参数设置为字符串值，用于在文档中高亮显示查询词。PostgreSQL 的默认值是 <code class="docutils literal notranslate"><span class="pre">&lt;b&gt;</span></code> 和 <code class="docutils literal notranslate"><span class="pre">&lt;/b&gt;</span></code>。</p>
<p>为 <code class="docutils literal notranslate"><span class="pre">max_words</span></code> 和 <code class="docutils literal notranslate"><span class="pre">min_words</span></code> 参数提供整数值，以确定最长和最短的标题。PostgreSQL 的默认值是 35 和 15。</p>
<p>为 <code class="docutils literal notranslate"><span class="pre">short_word</span></code> 参数提供一个整数值，以便在每个标题中丢弃这个长度或更少的字。PostgreSQL 的默认值是 3。</p>
<p>将 <code class="docutils literal notranslate"><span class="pre">highlight_all</span></code> 参数设置为 <code class="docutils literal notranslate"><span class="pre">True</span></code>，以使用整个文档来代替片段，并忽略 <code class="docutils literal notranslate"><span class="pre">max_words</span></code>、<code class="docutils literal notranslate"><span class="pre">min_words</span></code> 和 <code class="docutils literal notranslate"><span class="pre">short_word</span></code> 参数。这在 PostgreSQL 中是默认禁用的。</p>
<p>为 <code class="docutils literal notranslate"><span class="pre">max_fragments</span></code> 提供一个非零的整数值，以设置要显示的最大片段数。在 PostgreSQL 中默认是禁用的。</p>
<p>设置 <code class="docutils literal notranslate"><span class="pre">fragment_delimiter</span></code> 字符串参数来配置片段之间的定界符。PostgreSQL 的默认值是 <code class="docutils literal notranslate"><span class="pre">&quot;</span> <span class="pre">...</span> <span class="pre">&quot;</span></code>。</p>
<p>PostgreSQL 文档中有更多关于 <a class="reference external" href="https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-HEADLINE">高亮搜索结果</a> 的细节。</p>
<p>使用实例：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.contrib.postgres.search</span> <span class="kn">import</span> <span class="n">SearchHeadline</span><span class="p">,</span> <span class="n">SearchQuery</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">query</span> <span class="o">=</span> <span class="n">SearchQuery</span><span class="p">(</span><span class="s1">&#39;red tomato&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">entry</span> <span class="o">=</span> <span class="n">Entry</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">annotate</span><span class="p">(</span>
<span class="gp">... </span>    <span class="n">headline</span><span class="o">=</span><span class="n">SearchHeadline</span><span class="p">(</span>
<span class="gp">... </span>        <span class="s1">&#39;body_text&#39;</span><span class="p">,</span>
<span class="gp">... </span>        <span class="n">query</span><span class="p">,</span>
<span class="gp">... </span>        <span class="n">start_sel</span><span class="o">=</span><span class="s1">&#39;&lt;span&gt;&#39;</span><span class="p">,</span>
<span class="gp">... </span>        <span class="n">stop_sel</span><span class="o">=</span><span class="s1">&#39;&lt;/span&gt;&#39;</span><span class="p">,</span>
<span class="gp">... </span>    <span class="p">),</span>
<span class="gp">... </span><span class="p">)</span><span class="o">.</span><span class="n">get</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">entry</span><span class="o">.</span><span class="n">headline</span><span class="p">)</span>
<span class="go">Sandwich with &lt;span&gt;tomato&lt;/span&gt; and &lt;span&gt;red&lt;/span&gt; cheese.</span>
</pre></div>
</div>
<p>参见 <a class="reference internal" href="#postgresql-fts-search-configuration"><span class="std std-ref">更改搜索配置</span></a> 对 <code class="docutils literal notranslate"><span class="pre">config</span></code> 参数的解释。</p>
</div>
<div class="section" id="s-changing-the-search-configuration">
<span id="s-postgresql-fts-search-configuration"></span><span id="changing-the-search-configuration"></span><span id="postgresql-fts-search-configuration"></span><h2>更改搜索配置<a class="headerlink" href="#changing-the-search-configuration" title="永久链接至标题">¶</a></h2>
<p>你可以为 <a class="reference internal" href="#django.contrib.postgres.search.SearchVector" title="django.contrib.postgres.search.SearchVector"><code class="xref py py-class docutils literal notranslate"><span class="pre">SearchVector</span></code></a> 和 <a class="reference internal" href="#django.contrib.postgres.search.SearchQuery" title="django.contrib.postgres.search.SearchQuery"><code class="xref py py-class docutils literal notranslate"><span class="pre">SearchQuery</span></code></a> 指定 <code class="docutils literal notranslate"><span class="pre">config</span></code> 属性，以使用不同的搜索配置。这允许使用数据库定义的不同语言解析器和字典：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.contrib.postgres.search</span> <span class="kn">import</span> <span class="n">SearchQuery</span><span class="p">,</span> <span class="n">SearchVector</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Entry</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">annotate</span><span class="p">(</span>
<span class="gp">... </span>    <span class="n">search</span><span class="o">=</span><span class="n">SearchVector</span><span class="p">(</span><span class="s1">&#39;body_text&#39;</span><span class="p">,</span> <span class="n">config</span><span class="o">=</span><span class="s1">&#39;french&#39;</span><span class="p">),</span>
<span class="gp">... </span><span class="p">)</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">search</span><span class="o">=</span><span class="n">SearchQuery</span><span class="p">(</span><span class="s1">&#39;œuf&#39;</span><span class="p">,</span> <span class="n">config</span><span class="o">=</span><span class="s1">&#39;french&#39;</span><span class="p">))</span>
<span class="go">[&lt;Entry: Pain perdu&gt;]</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">config</span></code> 的值也可以储存在另一列中：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.db.models</span> <span class="kn">import</span> <span class="n">F</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Entry</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">annotate</span><span class="p">(</span>
<span class="gp">... </span>    <span class="n">search</span><span class="o">=</span><span class="n">SearchVector</span><span class="p">(</span><span class="s1">&#39;body_text&#39;</span><span class="p">,</span> <span class="n">config</span><span class="o">=</span><span class="n">F</span><span class="p">(</span><span class="s1">&#39;blog__language&#39;</span><span class="p">)),</span>
<span class="gp">... </span><span class="p">)</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">search</span><span class="o">=</span><span class="n">SearchQuery</span><span class="p">(</span><span class="s1">&#39;œuf&#39;</span><span class="p">,</span> <span class="n">config</span><span class="o">=</span><span class="n">F</span><span class="p">(</span><span class="s1">&#39;blog__language&#39;</span><span class="p">)))</span>
<span class="go">[&lt;Entry: Pain perdu&gt;]</span>
</pre></div>
</div>
</div>
<div class="section" id="s-weighting-queries">
<span id="s-postgresql-fts-weighting-queries"></span><span id="weighting-queries"></span><span id="postgresql-fts-weighting-queries"></span><h2>加权查询<a class="headerlink" href="#weighting-queries" title="永久链接至标题">¶</a></h2>
<p>每个字段在查询中的相关度可能不一样，所以在组合之前可以设置各种向量的权重：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.contrib.postgres.search</span> <span class="kn">import</span> <span class="n">SearchQuery</span><span class="p">,</span> <span class="n">SearchRank</span><span class="p">,</span> <span class="n">SearchVector</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">vector</span> <span class="o">=</span> <span class="n">SearchVector</span><span class="p">(</span><span class="s1">&#39;body_text&#39;</span><span class="p">,</span> <span class="n">weight</span><span class="o">=</span><span class="s1">&#39;A&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="n">SearchVector</span><span class="p">(</span><span class="s1">&#39;blog__tagline&#39;</span><span class="p">,</span> <span class="n">weight</span><span class="o">=</span><span class="s1">&#39;B&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">query</span> <span class="o">=</span> <span class="n">SearchQuery</span><span class="p">(</span><span class="s1">&#39;cheese&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Entry</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">annotate</span><span class="p">(</span><span class="n">rank</span><span class="o">=</span><span class="n">SearchRank</span><span class="p">(</span><span class="n">vector</span><span class="p">,</span> <span class="n">query</span><span class="p">))</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">rank__gte</span><span class="o">=</span><span class="mf">0.3</span><span class="p">)</span><span class="o">.</span><span class="n">order_by</span><span class="p">(</span><span class="s1">&#39;rank&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>权重应该是下列字母之一。默认情况下，这些权重分别是指数字 <code class="docutils literal notranslate"><span class="pre">0.1</span></code>、<code class="docutils literal notranslate"><span class="pre">0.2</span></code>、<code class="docutils literal notranslate"><span class="pre">0.4</span></code> 和 <code class="docutils literal notranslate"><span class="pre">1.0</span></code>。如果你希望以不同的方式对它们进行加权，请将四个浮点数的列表传递给 <a class="reference internal" href="#django.contrib.postgres.search.SearchRank" title="django.contrib.postgres.search.SearchRank"><code class="xref py py-class docutils literal notranslate"><span class="pre">SearchRank</span></code></a> 作为 <code class="docutils literal notranslate"><span class="pre">weights</span></code>，顺序与上述相同：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">rank</span> <span class="o">=</span> <span class="n">SearchRank</span><span class="p">(</span><span class="n">vector</span><span class="p">,</span> <span class="n">query</span><span class="p">,</span> <span class="n">weights</span><span class="o">=</span><span class="p">[</span><span class="mf">0.2</span><span class="p">,</span> <span class="mf">0.4</span><span class="p">,</span> <span class="mf">0.6</span><span class="p">,</span> <span class="mf">0.8</span><span class="p">])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Entry</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">annotate</span><span class="p">(</span><span class="n">rank</span><span class="o">=</span><span class="n">rank</span><span class="p">)</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">rank__gte</span><span class="o">=</span><span class="mf">0.3</span><span class="p">)</span><span class="o">.</span><span class="n">order_by</span><span class="p">(</span><span class="s1">&#39;-rank&#39;</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="section" id="s-performance">
<span id="performance"></span><h2>性能<a class="headerlink" href="#performance" title="永久链接至标题">¶</a></h2>
<p>使用这些函数都不需要特殊的数据库配置，但是，如果你搜索的记录超过几百条，你很可能会遇到性能问题。例如，全文搜索是一个比比较整数大小更密集的过程。</p>
<p>如果你要查询的所有字段都包含在一个特定的模型中，你可以创建一个与你希望使用的搜索向量相匹配的功能索引。PostgreSQL 文档中有关于 <a class="reference external" href="https://www.postgresql.org/docs/current/textsearch-tables.html#TEXTSEARCH-TABLES-INDEX">为全文搜索创建索引</a> 的详细介绍。</p>
<div class="section" id="s-searchvectorfield">
<span id="searchvectorfield"></span><h3><code class="docutils literal notranslate"><span class="pre">SearchVectorField</span></code><a class="headerlink" href="#searchvectorfield" title="永久链接至标题">¶</a></h3>
<dl class="class">
<dt id="django.contrib.postgres.search.SearchVectorField">
<em class="property">class </em><code class="descname">SearchVectorField</code><a class="headerlink" href="#django.contrib.postgres.search.SearchVectorField" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>如果这种方法变得太慢，你可以在你的模型中添加一个 <code class="docutils literal notranslate"><span class="pre">SearchVectorField</span></code>。你需要用触发器来填充它，例如，如 <a class="reference external" href="https://www.postgresql.org/docs/current/textsearch-features.html#TEXTSEARCH-UPDATE-TRIGGERS">PostgreSQL 文档</a> 中所述。然后，你可以像查询一个注解的 <code class="docutils literal notranslate"><span class="pre">SearchVector</span></code> 一样查询这个字段：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">Entry</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">search_vector</span><span class="o">=</span><span class="n">SearchVector</span><span class="p">(</span><span class="s1">&#39;body_text&#39;</span><span class="p">))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Entry</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">search_vector</span><span class="o">=</span><span class="s1">&#39;cheese&#39;</span><span class="p">)</span>
<span class="go">[&lt;Entry: Cheese on Toast recipes&gt;, &lt;Entry: Pizza recipes&gt;]</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="s-trigram-similarity">
<span id="trigram-similarity"></span><h2>三元相似度<a class="headerlink" href="#trigram-similarity" title="永久链接至标题">¶</a></h2>
<p>另一种搜索方法是三元相似度。trigram 是一组连续的三个字符。除了 <a class="reference internal" href="lookups.html#std:fieldlookup-trigram_similar"><code class="xref std std-lookup docutils literal notranslate"><span class="pre">trigram_similar</span></code></a> 查找之外，你还可以使用其他几个表达式。</p>
<p>要使用它们，你需要激活 PostgreSQL 上的 <a class="reference external" href="https://www.postgresql.org/docs/current/pgtrgm.html">pg_trgm 扩展</a> 。你可以使用 <a class="reference internal" href="operations.html#django.contrib.postgres.operations.TrigramExtension" title="django.contrib.postgres.operations.TrigramExtension"><code class="xref py py-class docutils literal notranslate"><span class="pre">TrigramExtension</span></code></a> 迁移操作来安装它。</p>
<div class="section" id="s-trigramsimilarity">
<span id="trigramsimilarity"></span><h3><code class="docutils literal notranslate"><span class="pre">TrigramSimilarity</span></code><a class="headerlink" href="#trigramsimilarity" title="永久链接至标题">¶</a></h3>
<dl class="class">
<dt id="django.contrib.postgres.search.TrigramSimilarity">
<em class="property">class </em><code class="descname">TrigramSimilarity</code>(<em>expression</em>, <em>string</em>, <em>**extra</em>)<a class="headerlink" href="#django.contrib.postgres.search.TrigramSimilarity" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>接受一个字段名或表达式，以及一个字符串或表达式。返回两个参数之间的三元相似度。</p>
<p>使用实例：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.contrib.postgres.search</span> <span class="kn">import</span> <span class="n">TrigramSimilarity</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Author</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">&#39;Katy Stevens&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Author</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">&#39;Stephen Keats&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">test</span> <span class="o">=</span> <span class="s1">&#39;Katie Stephens&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Author</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">annotate</span><span class="p">(</span>
<span class="gp">... </span>    <span class="n">similarity</span><span class="o">=</span><span class="n">TrigramSimilarity</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="n">test</span><span class="p">),</span>
<span class="gp">... </span><span class="p">)</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">similarity__gt</span><span class="o">=</span><span class="mf">0.3</span><span class="p">)</span><span class="o">.</span><span class="n">order_by</span><span class="p">(</span><span class="s1">&#39;-similarity&#39;</span><span class="p">)</span>
<span class="go">[&lt;Author: Katy Stevens&gt;, &lt;Author: Stephen Keats&gt;]</span>
</pre></div>
</div>
</div>
<div class="section" id="s-trigramdistance">
<span id="trigramdistance"></span><h3><code class="docutils literal notranslate"><span class="pre">TrigramDistance</span></code><a class="headerlink" href="#trigramdistance" title="永久链接至标题">¶</a></h3>
<dl class="class">
<dt id="django.contrib.postgres.search.TrigramDistance">
<em class="property">class </em><code class="descname">TrigramDistance</code>(<em>expression</em>, <em>string</em>, <em>**extra</em>)<a class="headerlink" href="#django.contrib.postgres.search.TrigramDistance" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>接受一个字段名或表达式，以及一个字符串或表达式。返回两个参数之间的三元距离。</p>
<p>使用实例：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.contrib.postgres.search</span> <span class="kn">import</span> <span class="n">TrigramDistance</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Author</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">&#39;Katy Stevens&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Author</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">&#39;Stephen Keats&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">test</span> <span class="o">=</span> <span class="s1">&#39;Katie Stephens&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Author</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">annotate</span><span class="p">(</span>
<span class="gp">... </span>    <span class="n">distance</span><span class="o">=</span><span class="n">TrigramDistance</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="n">test</span><span class="p">),</span>
<span class="gp">... </span><span class="p">)</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">distance__lte</span><span class="o">=</span><span class="mf">0.7</span><span class="p">)</span><span class="o">.</span><span class="n">order_by</span><span class="p">(</span><span class="s1">&#39;distance&#39;</span><span class="p">)</span>
<span class="go">[&lt;Author: Katy Stevens&gt;, &lt;Author: Stephen Keats&gt;]</span>
</pre></div>
</div>
</div>
</div>
</div>


          </div>
        </div>
      </div>
      
        
          <div class="yui-b" id="sidebar">
            
      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
        <div class="sphinxsidebarwrapper">
  <h3><a href="../../../contents.html">Table of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">全文搜索</a><ul>
<li><a class="reference internal" href="#the-search-lookup"><code class="docutils literal notranslate"><span class="pre">search</span></code> 查找</a></li>
<li><a class="reference internal" href="#searchvector"><code class="docutils literal notranslate"><span class="pre">SearchVector</span></code></a></li>
<li><a class="reference internal" href="#searchquery"><code class="docutils literal notranslate"><span class="pre">SearchQuery</span></code></a></li>
<li><a class="reference internal" href="#searchrank"><code class="docutils literal notranslate"><span class="pre">SearchRank</span></code></a></li>
<li><a class="reference internal" href="#searchheadline"><code class="docutils literal notranslate"><span class="pre">SearchHeadline</span></code></a></li>
<li><a class="reference internal" href="#changing-the-search-configuration">更改搜索配置</a></li>
<li><a class="reference internal" href="#weighting-queries">加权查询</a></li>
<li><a class="reference internal" href="#performance">性能</a><ul>
<li><a class="reference internal" href="#searchvectorfield"><code class="docutils literal notranslate"><span class="pre">SearchVectorField</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#trigram-similarity">三元相似度</a><ul>
<li><a class="reference internal" href="#trigramsimilarity"><code class="docutils literal notranslate"><span class="pre">TrigramSimilarity</span></code></a></li>
<li><a class="reference internal" href="#trigramdistance"><code class="docutils literal notranslate"><span class="pre">TrigramDistance</span></code></a></li>
</ul>
</li>
</ul>
</li>
</ul>

  <h4>上一个主题</h4>
  <p class="topless"><a href="operations.html"
                        title="上一章">数据库迁移操作</a></p>
  <h4>下一个主题</h4>
  <p class="topless"><a href="validators.html"
                        title="下一章">验证器</a></p>
  <div role="note" aria-label="source link">
    <h3>本页</h3>
    <ul class="this-page-menu">
      <li><a href="../../../_sources/ref/contrib/postgres/search.txt"
            rel="nofollow">显示源代码</a></li>
    </ul>
   </div>
<div id="searchbox" style="display: none" role="search">
  <h3>快速搜索</h3>
    <div class="searchformwrapper">
    <form class="search" action="../../../search.html" method="get">
      <input type="text" name="q" />
      <input type="submit" value="转向" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    </div>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
              <h3>Last update:</h3>
              <p class="topless">7月 23, 2021</p>
          </div>
        
      
    </div>

    <div id="ft">
      <div class="nav">
    &laquo; <a href="operations.html" title="数据库迁移操作">previous</a>
     |
    <a href="../../index.html" title="API 参考" accesskey="U">up</a>
   |
    <a href="validators.html" title="验证器">next</a> &raquo;</div>
    </div>
  </div>

      <div class="clearer"></div>
    </div>
  </body>
</html>